<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/5/8
 * Time: 16:08
 */

namespace bgb\weixin;

use bgb\Http;

/**
 * 微信网页授权
 * Class Authorize
 * @package bgb\weixin
 */
class Authorize
{

    use Http;

    const AUTHORIZE_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize'; //授权链接

    const ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/sns/oauth2/access_token'; //通过code换取网页授权access_token URL

    const GET_USER_INFO = 'https://api.weixin.qq.com/sns/userinfo'; //拉取用户信息(需scope为 snsapi_userinfo)

    const GET_USER_INFO_WITH_UNION_ID = 'https://api.weixin.qq.com/cgi-bin/user/info'; //获取用户基本信息(UnionID机制)


    protected $appid;
    protected $appsecret;
    protected $callback;

    const STATE_KEY = 'WXSTATE:KEY';

    public function __construct($appid, $appsecret, $callback)
    {
        $this->appid = $appid;
        $this->appsecret = $appsecret;
        $this->callback = $callback;
    }

    /**
     * 获取网页授权url
     * @return string
     */
    public function getAuthorizeUrl()
    {
        session(self::STATE_KEY, uniqid());

        $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='. $this->appid
            .'&redirect_uri=' . urlencode($this->callback) .
            '&response_type=code&scope=snsapi_userinfo&state=' . session(self::STATE_KEY).'#wechat_redirect';

        return $url;

    }

    /**
     * 回调方法中执行该方法传入code 与 state 会返回 返回token|openid 等信息 后续根据实际业务需求进行相关处理 或 告知执行失败原因
     * @param $code
     * @param $state
     * @return array|mixed
     */
    public function callback($code, $state)
    {
        try {

            if ($state != session(self::STATE_KEY)) {
                throw new \Exception('STATE 参数校验失败');
            }

            $result = $this->getRequest(self::ACCESS_TOKEN_URL, [
                'appid' => $this->appid,
                'secret' => $this->appsecret,
                'code' => $code,
                'grant_type' => 'authorization_code'
            ]);

            if (isset($result['errorcode']) && $result['errorcode'] > 0) {
                throw new \Exception('TOKEN获取异常:' . $result['errmsg']);
            }

            return ['status' => true, 'data' => $result];

        } catch (\Exception $exception) {
            return ['status' => false, 'msg' => $exception->getMessage()];
        }

    }

    /**
     * 拉取用户信息(需scope为 snsapi_userinfo)
     * @param $accessToken string 用户登录时获取的accesstoken
     * @param $openid
     * @return mixed
     */
    public function getUserInfo($accessToken, $openid)
    {
        return $this->getRequest(self::GET_USER_INFO, [
            'access_token' => $accessToken,
            'openid' => $openid,
            'lang' => 'zh_CN',
        ]);
    }

    /**
     * 获取用户基本信息(UnionID机制)
     * @param $accessToken string 公众号获取token
     * @param $openid
     * @return mixed
     */
    public function getUserInfoWithUnionID($accessToken, $openid)
    {
        return $this->getRequest(self::GET_USER_INFO_WITH_UNION_ID, [
            'access_token' => $accessToken,
            'openid' => $openid,
            'lang' => 'zh_CN',
        ]);
    }

}